package com.zhiche.wms.service.outbound.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zhiche.wms.configuration.MyConfigurationProperties;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.InterfaceEventEnum;
import com.zhiche.wms.core.supports.enums.SysSourceEnum;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.HttpClientUtil;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.domain.mapper.log.CancelStoreLogMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundShipLineMapper;
import com.zhiche.wms.domain.model.base.StoreLocation;
import com.zhiche.wms.domain.model.log.CancelStoreLog;
import com.zhiche.wms.domain.model.log.ItfExplogLine;
import com.zhiche.wms.domain.model.otm.OtmOrderRelease;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeHeader;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeLine;
import com.zhiche.wms.domain.model.outbound.OutboundShipHeader;
import com.zhiche.wms.domain.model.outbound.OutboundShipLine;
import com.zhiche.wms.domain.model.stock.Stock;
import com.zhiche.wms.domain.model.stock.StockProperty;
import com.zhiche.wms.domain.model.sys.User;
import com.zhiche.wms.dto.outbound.OutboundShipDTO;
import com.zhiche.wms.dto.outbound.OutboundShipQuitResultDTO;
import com.zhiche.wms.service.base.IBusinessDocNumberService;
import com.zhiche.wms.service.base.IStoreLocationService;
import com.zhiche.wms.service.constant.SourceSystem;
import com.zhiche.wms.service.constant.Status;
import com.zhiche.wms.service.log.IItfExplogLineService;
import com.zhiche.wms.service.otm.IOtmOrderReleaseService;
import com.zhiche.wms.service.outbound.IOutboundNoticeHeaderService;
import com.zhiche.wms.service.outbound.IOutboundNoticeLineService;
import com.zhiche.wms.service.outbound.IOutboundShipHeaderService;
import com.zhiche.wms.service.outbound.IOutboundShipLineService;
import com.zhiche.wms.service.stock.IStockService;
import com.zhiche.wms.service.sys.IUserService;
import com.zhiche.wms.service.utils.CommonFields;
import com.zhiche.wms.service.utils.CommonMethod;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 出库单明细 服务实现类
 * </p>
 *
 * @author qichao
 * @since 2018-06-08
 */
@Service
public class OutboundShipLineServiceImpl extends ServiceImpl<OutboundShipLineMapper, OutboundShipLine> implements IOutboundShipLineService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OutboundShipLineServiceImpl.class);

    @Autowired
    private IOutboundNoticeHeaderService outboundNoticeHeaderService;
    @Autowired
    private IOutboundNoticeLineService outboundNoticeLineService;
    @Autowired
    private IBusinessDocNumberService businessDocNumberService;
    @Autowired
    private IStockService stockService;
    @Autowired
    private SnowFlakeId snowFlakeId;
    @Autowired
    private IStoreLocationService locationService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IOutboundShipHeaderService shipHeaderService;
    @Autowired
    private IOtmOrderReleaseService releaseService;
    @Autowired
    private IItfExplogLineService explogLineService;
    @Autowired
    private MyConfigurationProperties properties;
    @Autowired
    private CancelStoreLogMapper cancelStoreLogMapper;

    public OutboundShipDTO getPutWaylineById(Long id) {
        OutboundShipDTO outboundPutawayDTO = null;
        try {
            outboundPutawayDTO = this.baseMapper.getPutWayByLineId(id);
        } catch (Exception e) {
            LOGGER.error(e.toString());
            throw new BaseException("查询出库信息出错");
        }
        return outboundPutawayDTO;
    }

    @Override
    public List<OutboundShipQuitResultDTO> selectQuitInfoByParams(HashMap<String, Object> params) {
        return this.baseMapper.selectQuitInfoByParams(params);
    }

    @Override
    public List<OutboundShipQuitResultDTO> selectQuitInfo (HashMap<String, Object> params) {
        return this.baseMapper.selectQuitInfo(params);
    }

    @Override
    public Page<OutboundShipDTO> queryOutShipLinePage(Page<OutboundShipDTO> page) {
        Wrapper<OutboundShipDTO> ew = buildCondition(page.getCondition());
        List<OutboundShipDTO> dtoList = this.baseMapper.queryLineListByPage(page, ew);
        page.setRecords(dtoList);
        return page;
    }

    /**
     * 出库记录导出
     */
    @Override
    public List<OutboundShipDTO> queryExportOSData(Map<String, String> condition) {
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        Wrapper<OutboundShipDTO> ew = new EntityWrapper<>();
        if (StringUtils.isBlank(condition.get("houseId"))) {
            throw new BaseException("仓库不能为空");
        }
        ew.eq("store_house_id", condition.get("houseId"));
        if (StringUtils.isNotBlank(condition.get("vinNo"))) {
            ew.like("lot_no1", condition.get("vinNo"));
        }
        if (StringUtils.isNotBlank(condition.get("materielCode"))) {
            ew.like("materiel_code", condition.get("materielCode"));
        }
        if (StringUtils.isNotBlank(condition.get("startDate"))) {
            ew.ge("gmt_create", condition.get("startDate"));
        }
        if (StringUtils.isNotBlank(condition.get("endDate"))) {
            ew.le("gmt_create", condition.get("endDate"));
        }
        ew.orderBy("id", false);
        return baseMapper.selectExportOSData(ew);
    }

    private Wrapper<OutboundShipDTO> buildCondition(Map<String, Object> condition) {
        Wrapper<OutboundShipDTO> ew = new EntityWrapper<>();
        if (condition.containsKey("houseId") && Objects.nonNull(condition.get("houseId"))) {
            ew.eq("store_house_id", condition.get("houseId").toString());
        }
        if (condition.containsKey("materielCode") && Objects.nonNull(condition.get("materielCode"))) {
            ew.like("materiel_code", condition.get("materielCode").toString());
        }
        if (condition.containsKey("startDate") && Objects.nonNull(condition.get("startDate"))) {
            ew.ge("gmt_create", condition.get("startDate").toString());
        }
        if (condition.containsKey("endDate") && Objects.nonNull(condition.get("endDate"))) {
            ew.le("gmt_create", condition.get("endDate").toString());
        }
        if (condition.containsKey("vinNo") && Objects.nonNull(condition.get("vinNo")) && StringUtils.isNotEmpty((String)condition.get("vinNo"))) {
            String vin = condition.get("vinNo").toString();
            List<String> vins = Arrays.asList(CommonMethod.setVins(vin));
            ew.andNew().in("lot_no1", vins).or().like("lot_no1", vin);
        }
        ew.orderBy("id", false);
        return ew;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized OutboundShipHeader shipByNoticeLineId(Long noticeLineId, String outboundType, String genMethod) {
        LOGGER.info("调用出库方法出库 noticeLineId : {}",noticeLineId);
        //获取入库通知单明细
        OutboundNoticeLine outboundNoticeLine = outboundNoticeLineService.selectById(noticeLineId);
        LOGGER.info("出库通知单是否存在 outboundNoticeLine ：{} ",outboundNoticeLine);
        if (Objects.isNull(outboundNoticeLine)) {
            throw new BaseException("出库通知单明细不存在！");
        }

        if (outboundNoticeLine.getStatus().equals(Status.Inbound.ALL)) {
            throw new BaseException("已出库不能重复出库！");
        }

        if (outboundNoticeLine.getStatus().equals(Status.Inbound.CANCEL)) {
            throw new BaseException("出库已取消，不能出库！");
        }

        User loginUser = userService.queryLoginUser(genMethod);

        //获取入库通知单头
        OutboundNoticeHeader outboundNoticeHeader =
                outboundNoticeHeaderService.selectById(outboundNoticeLine.getHeaderId());

        StockProperty stockProperty = new StockProperty();
        BeanUtils.copyProperties(outboundNoticeLine, stockProperty);
        stockProperty.setStoreHouseId(outboundNoticeHeader.getStoreHouseId());

        //得到可发库存
        List<Stock> stockList = stockService.queryStockList(stockProperty);
        LOGGER.info("出库获取可出库的库存数据量 stockList.size ： {} ",stockList.size());
        if (CollectionUtils.isEmpty(stockList)) throw new BaseException(outboundNoticeLine.getLotNo1() + "未找到匹配库存！");
        Stock stock = stockList.get(0);
        //出库记录头表
        OutboundShipHeader outboundShipHeader = new OutboundShipHeader();
        BeanUtils.copyProperties(outboundNoticeHeader, outboundShipHeader);
        outboundShipHeader.setNoticeId(outboundNoticeHeader.getId());
        outboundShipHeader.setOutboundNo(businessDocNumberService.getOutboundShipNo());
        outboundShipHeader.setId(snowFlakeId.nextId());
        outboundShipHeader.setType(outboundType);
        outboundShipHeader.setGenMethod(genMethod);
        outboundShipHeader.setStatus(Status.AUDIT);
        outboundShipHeader.setUserCreate(loginUser.getName());
        outboundShipHeader.setUserModified(loginUser.getName());
        outboundShipHeader.setGmtCreate(null); //创建时间、修改时间使用数据库自动处理
        outboundShipHeader.setGmtModified(null);

        //出库单明细
        OutboundShipLine outboundShipLine = new OutboundShipLine();
        BeanUtils.copyProperties(outboundNoticeLine, outboundShipLine);
        outboundShipLine.setHeaderId(outboundShipHeader.getId());
        outboundShipLine.setNoticeLineId(outboundNoticeLine.getId());
        outboundShipLine.setLocationId(stock.getLocationId());
        StoreLocation storeLocation = locationService.selectLocationByLocationId(stock.getLocationId());
        if (storeLocation != null) {
            outboundShipLine.setLocationNo(storeLocation.getStoreAreaName() + " " + storeLocation.getName());
        }
        outboundShipLine.setOutboundQty(outboundNoticeLine.getExpectQty());
        outboundShipLine.setOutboundNetWeight(outboundNoticeLine.getExpectNetWeight());
        outboundShipLine.setOutboundGrossWeight(outboundNoticeLine.getExpectGrossWeight());
        outboundShipLine.setOutboundGrossCubage(outboundNoticeLine.getExpectGrossCubage());
        outboundShipLine.setOutboundPackedCount(outboundNoticeLine.getExpectPackedCount());
        outboundShipLine.setId(snowFlakeId.nextId());
        outboundShipLine.setGmtCreate(null);//创建时间、修改时间使用数据库自动处理
        outboundShipLine.setGmtModified(null);
        outboundShipHeader.addOutboundShipLine(outboundShipLine);

        //保存并审核移位单、入库单
        boolean result = shipHeaderService.insertMovementByShip(outboundShipHeader, loginUser) && shipHeaderService.saveShip(outboundShipHeader);

        if (!result) {
            throw new BaseException("出库失败");
        }
        outboundNoticeHeaderService.updateStatus(outboundNoticeHeader.getId(),noticeLineId);
        // 如果运单生成的出库  需要调整运单状态为已出库
        shipHeaderService.setReleaseAndStatusLog(noticeLineId, outboundNoticeLine, loginUser);

        return outboundShipHeader;
    }

    /**
     * 用于BMS手动补发运数据
     */
    @Override
    public void wmsShipHandler(Map<String, String> condition) {
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        String shipmentGids = condition.get("shipmentGids");
        if (StringUtils.isBlank(shipmentGids)) {
            throw new BaseException("请输入正确的指令号,逗号分隔");
        }
        EntityWrapper<OtmOrderRelease> oorEW = new EntityWrapper<>();
        //oorEW.eq("status", TableStatusEnum.STATUS_BS_DISPATCH.getCode())
        oorEW.isNotNull("ship_date");
        oorEW.in("shipment_gid", shipmentGids);
        oorEW.orderBy("id", false);
        int count = releaseService.selectCount(oorEW);
        if (count == 0) {
            throw new BaseException("WMS未发运,请联系现场处理");
        }
        Page<OtmOrderRelease> pg = new Page<>();
        pg.setSize(count);
        pg.setCurrent(1);
        List<OtmOrderRelease> orderReleases = releaseService.selectPage(pg, oorEW).getRecords();
        LOGGER.info("wms共查询到-----{}条-----已发运车辆", count);
        int i = 0;
        for (OtmOrderRelease oor : orderReleases) {
            EntityWrapper<ItfExplogLine> logEW = new EntityWrapper<>();
            logEW.eq("relation_id", oor.getId())
                    .eq("export_type", InterfaceEventEnum.BS_OP_DELIVERY.getCode());
            List<ItfExplogLine> lines = explogLineService.selectList(logEW);
            if (CollectionUtils.isNotEmpty(lines)) {
                ItfExplogLine explogLine = lines.get(0);
                // TMS正式地址: http://10.20.30.155:8280/lisa-tms/shipTask/shipDataForBMS
                try {
                    LOGGER.info("wms推送TMS发运 url:{},参数: releaseGid:{},shipmentGid:{} 次数i:{}",
                            properties.getShipDataForBMS(),
                            oor.getReleaseGid(),
                            oor.getShipmentGid(), ++i);
                    String resJson = HttpClientUtil.postJson(properties.getShipDataForBMS(), null, explogLine.getDataContent(), 60000);
                    LOGGER.info("wms推送TMS发运结果-->{}", resJson);
                } catch (Exception e) {
                    LOGGER.error("wms推送TMS发运失败-->{}", e);
                    throw new BaseException("WMS推送发运传送TMS失败");
                }
            } else {
                LOGGER.error("WMS推送发运失败--->or的表主键:{},运单:{},指令:{}", oor.getId(), oor.getReleaseGid(), oor.getShipmentGid());
                throw new BaseException("WMS发运未成功推送数据,请联系IT 运单号: " + oor.getReleaseGid());
            }
        }

    }

    @Override
    public Page<CancelStoreLog> queryCancleList (Page<CancelStoreLog> page) {
        EntityWrapper<CancelStoreLog> ew = new EntityWrapper<>();
        Map<String,Object> condition = page.getCondition();
        if(null != condition){
            if(Objects.nonNull(condition.get("startDate")) && StringUtils.isNotEmpty((String)condition.get("startDate"))){
                ew.gt("csl.gmt_create",condition.get("startDate"));
            }
            if(Objects.nonNull(condition.get("endDate")) && StringUtils.isNotEmpty((String)condition.get("endDate"))){
                ew.lt("csl.gmt_create",condition.get("endDate"));
            }
        }
        List<CancelStoreLog> cancelStoreLogs = cancelStoreLogMapper.queryCancleList(page,ew);
        return page.setRecords(cancelStoreLogs);
    }

    @Override
    public Map<String, Object> queryShipDate (String releaseGid) {
        if (StringUtils.isBlank(releaseGid)) {
            throw new BaseException("系统运单号不能为空");
        }
        EntityWrapper<OtmOrderRelease> ew = new EntityWrapper<>();
        ew.eq("release_gid", releaseGid);
        ew.ne(CommonFields.STATUS.getCode(), TableStatusEnum.STATUS_50.getCode());
        ew.isNotNull("ship_date");
        OtmOrderRelease otmOrderRelease = releaseService.selectOne(ew);
        Map<String, Object> result = new HashMap<>();
        if (null == otmOrderRelease) {
            result.put("shipDate", null);
            return result;
        }
        result.put("shipDate", otmOrderRelease.getShipDate());
        return result;
    }

}
